// 导入必要的工具函数
import { clearTimer, setTimer } from '$/utils/index.js'

// 导入 VueUse 的事件总线功能
import { useEventBus } from '@vueuse/core'
// 导入 Day.js 日期处理库
import dayjs from 'dayjs'
// 导入 Day.js 插件以支持持续时间操作
import duration from 'dayjs/plugin/duration'

// 导入 Element-Plus 的消息提示组件
import { ElMessage } from 'element-plus'
// 导入 Nanoid 用于生成唯一标识符
import { nanoid } from 'nanoid'
// 导入 Pinia 的 Store 定义函数
import { defineStore } from 'pinia'

// 扩展 Day.js 以支持持续时间操作
dayjs.extend(duration)

// 定义并导出一个名为 useTaskStore 的 Pinia Store
export const useTaskStore = defineStore(
  'app-task',
  () => {
    // 创建并使用事件总线
    const event = useEventBus('app-task')

    // 定义任务模型数组，包含不同类型的预定义任务
    const model = ref([
      {
        label: 'device.control.install',
        value: 'install',
      },
      {
        label: 'device.control.capture',
        value: 'screenshot',
      },
      {
        label: 'device.control.shell.name',
        value: 'shell',
      },
    ])

    // 定义任务列表数组，用于存储用户添加的任务
    const list = ref([])

    // 添加任务到列表中
    function add(form) {
      // 创建任务对象，包括表单数据、唯一标识符、初始状态等
      const task = {
        ...form,
        timerId: void 0,
        id: nanoid(),
        taskStatus: 'start',
        formatTimeout: dayjs(form.timeout).format('YYYY-MM-DD HH:mm:ss'),
      }

      // 触发事件以通知其他组件或进行其他操作
      event.emit(task)

      // 将任务添加到任务列表中
      list.value.push(task)
    }

    // 计算任务的超时或间隔时间
    function getTimeout(task) {
      let value = 0

      // 根据任务的计时类型计算时间值
      const { timerType } = task
      if (timerType === 'timeout') {
        value = dayjs(task.timeout).diff(dayjs())
      }
      else if (timerType === 'interval') {
        value = dayjs
          .duration(task.interval, task.intervalType)
          .asMilliseconds()
      }

      return value
    }

    // 启动任务
    function start({ task, handler }) {
      // 获取任务的计时类型和设备列表
      const { timerType, devices } = task

      // 解析任务的附加文件列表
      const files = task.extra ? task.extra.split(',') : void 0

      // 计算任务的超时时间
      const timeout = getTimeout(task)

      // 如果任务已经过期，则显示警告消息并返回 false
      if (timeout < 0) {
        ElMessage.warning(window.t('device.task.timeout.expired'))
        return false
      }

      // 设置任务的计时器
      task.timerId = setTimer(
        timerType,
        () => {
          // 执行任务处理函数，并根据任务类型决定是否停止任务
          handler(devices, { files })
          if (['timeout'].includes(timerType)) {
            stop(task)
          }
        },
        timeout,
      )

      // 更新任务状态为进行中
      Object.assign(task, {
        taskStatus: 'progress',
      })
    }

    // 停止任务
    function stop(task) {
      // 清除任务的计时器，并更新任务状态为已完成
      const { timerType, timerId } = task
      if (timerId) {
        clearTimer(timerType, timerId)
        Object.assign(task, {
          timerId: void 0,
          taskStatus: 'finished',
        })
      }
    }

    // 重新启动任务
    function restart(task) {
      // 触发事件以重新启动任务
      event.emit(task)
    }

    // 移除任务
    function remove(task) {
      // 停止任务并从列表中移除
      stop(task)
      list.value = list.value.filter(item => item.id !== task.id)
    }

    // 移除所有选定的任务
    function removeAll(tasks) {
      // 遍历任务列表并移除每个任务
      for (let index = 0; index < tasks.length; index++) {
        const item = tasks[index]
        remove(item)
      }
    }

    // 监听特定类型的事件
    function on(name, callback) {
      // 当事件总线接收到事件时，根据任务类型调用回调函数
      event.on((...args) => {
        const [{ taskType }] = args
        if (taskType !== name) {
          return false
        }
        callback(...args)
      })

      return event
    }

    // 发送自定义事件
    function emit(name, args) {
      // 触发事件并传递附加参数
      event.emit({ taskType: name, ...args })
      return event
    }

    // 返回 Store 的状态和操作函数
    return {
      event,
      on,
      emit,
      list,
      model,
      add,
      start,
      stop,
      restart,
      remove,
      removeAll,
    }
  },
  {
    // 配置持久化选项，以确保任务列表在页面刷新后仍然可用
    persist: {
      paths: ['list'],
    },
  },
)
